<?php

Yii::import("application.components.evaluators.Compiler");

/**
 * Kelas penyedia operasi grading 
 */
class GradingController extends CServiceController {

    private $model = null;
    
    protected function afterAction($action) {
        if ($this->model != null) {
            $handle = fopen("log/receiver.log" , "a+");
            $action = "";
            switch ($this->model->action) {
                case 0 : $action = "Compile"; break;
                case 1 : $action = "Grade"; break;
                case 2 : $action = "Execute"; break;
            }
            fprintf($handle , "[%s] Server %s received '%s' request #".$this->model->id."\n" , date("d/m/y h:i:s") , $_SERVER["SERVER_ADDR"] , $action);
            fclose($handle);
        }
        
        return parent::afterAction($action);
    }

    public function actionCompile() {
        $this->model = new GradeRequest();
        $this->model->action = GradeRequest::ACTION_COMPILE;
        $zipped = isset($_GET['flat']) ? false : true;
        $this->updateModel($zipped);

        ///TODO: Dispatch requests
        $this->dispatchRequest();

        $this->setReplyAttribute('request_id', $this->model->id);
    }
    
    public function actionDownloadArchive() {
        $model = $this->loadModel();
        ob_clean();

        header('Content-type: application/octet-stream');
        header('Content-Disposition: attachment; filename="'.$model->id . '-' .$model->source_file.'"');
        echo $model->file;
        exit;
    }

    public function actionGrade() {
        $this->model = new GradeRequest();
        $this->model->action = GradeRequest::ACTION_GRADE;
        $zipped = isset($_GET['flat']) ? false : true;
        $this->updateModel($zipped);

        ///TODO: Dispatch requests
        $this->dispatchRequest();

        $this->setReplyAttribute('request_id', $this->model->id);
    }

    public function actionExecute() {
        $this->model = new GradeRequest();
        $this->model->action = GradeRequest::ACTION_EXECUTE;
        $zipped = isset($_GET['flat']) ? false : true;
        $this->updateModel($zipped);

        ///TODO: Dispatch requests
        $this->dispatchRequest();

        $this->setReplyAttribute('request_id', $this->model->id);
    }

    public function actionRegrade() {
        $this->loadModel();
        $this->model->status = GradeRequest::STATUS_PENDING;
        $this->model->save();

        ///TODO: Dispatch requests
        $this->dispatchRequest();

        $this->setReplyAttribute('request_id', $this->model->id);
        $this->setReply(true, "Ok");
    }

    public function actionRecompile() {
        $this->loadModel();
        $this->model->status = GradeRequest::STATUS_PENDING;
        $this->model->save();

        $this->dispatchRequest();

        $this->setReplyAttribute('request_id', $this->model->id);
        $this->setReply(true, "Ok");
    }

    public function actionDetail() {
        $this->loadModel();
        $this->setReply(true, "Record found");
        $attr = $this->model->attributes;
        $attr["file"] = null;
        $attr["report"] = json_decode($attr["report"], true);
        $this->setReplyAttribute("detail", $attr);
    }

    /**
     * Operasi melaporkan hasil grading dan menuliskannya kembali ke basis data 
     */
    public function actionReport() {
        $this->loadModel();
        if (isset($_POST['GradingReport'])) {
            $this->model->report = $_POST['GradingReport'];
            $this->setReply(true, "Report received");
        } else {
            $this->setReply(false, "No report specified");
        }
    }

    protected function dispatchRequest() {
        ///TODO: Implement
//        if ($this->model !== null) {
//            if ($this->model->mode == GradeRequest::MODE_SYNCHRONOUS) {
//                $post = array(
//                    'grade_request' => $this->model->attributes,
//                    'evaluation_set' => $this->model->evaluationset->attributes
//                );
//
////                $return = Yii::app()->curl->run("http://localhost/lz-test/grading/dummy-compile.php" , false , $post);
////                $this->setReplyAttribute('data', array('result' => json_decode($return , true)));
//                ///Dummy, it should be on other server
//                if ($this->model->action == GradeRequest::ACTION_COMPILE) {
//                    $compiler = new Compiler($this->model);
//
//                    $return = $compiler->compileSource($output);
//                    
//                    $result = array();
//                    if ($return == "0") { //Success
//                        $this->setReply(true , "Compile success");
//                    } else {
//                        $this->setReply(false , "Compile failed");
//                    }
//
//                    $result['output'] = $output;
//                    
//                    $this->setReplyAttribute('compile_result', $result);
//
//                    $compiler->cleanup();
//                }
//            } else if ($this->model->mode == GradeRequest::MODE_ASYNCHRONOUS) {
//                if ($this->model->request->callback_url == "") {
//                    $this->setReply(false, "Asynchronous request must be with callback url");
//                } else {
//                    
//                }
//            }
//        }
        $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
        $str = "Wakeup";
        socket_sendto($sock, $str, strlen($str), 0, "127.0.0.1", 22022);
        socket_close($sock);
    }

    protected function loadModel() {
        if (isset($_GET['id'])) {
            $id = $_GET['id'];
            $this->model = GradeRequest::model()->findByPk($id);
            if ($this->model === null)
                throw new CHttpException(412, "No record found");
            else {
                return $this->model;
            }
        }
        else
            throw new CHttpException(412, "No record found");
    }

    protected function createTempDir($dir = false, $prefix = 'php') {
        $tempfile = tempnam(sys_get_temp_dir(), '');
        if (file_exists($tempfile)) {
            unlink($tempfile);
        }
        mkdir($tempfile);
        if (is_dir($tempfile)) {
            return $tempfile;
        }
    }

    protected function updateModel($zipped = true) {
        $model = $this->model;
        if ($model !== null && isset($_POST['GradeRequest'])) {
            $model->setAttributes($_POST['GradeRequest']);

            if ($model->validate()) {
                if ($zipped) {
                    if (isset($_FILES['GradeRequest']['tmp_name']['file']) && $_FILES['GradeRequest']['tmp_name']['file'] !== "") {
                        $model->file = file_get_contents($_FILES['GradeRequest']['tmp_name']['file']);

                        //if (!isset($_POST['GradeRequest']['source_file']) && $_POST['GradeRequest']['source_file'] == "")
                        $model->source_file = $_FILES['GradeRequest']['name']['file'];
                    }
                } else {
                    if (isset($_POST['files'])) {
                        if (count($_POST['files']) == 1) {
                            foreach ($_POST['files'] as $file) {
                                $model->file = $file['content'];
                                $model->source_file = $file['name'];
                            }
                        } else {
                            $tmpDir = $this->createTempDir();
                            foreach ($_POST['files'] as $file) {
                                file_put_contents($tmpDir . "/" . $file['name'], $file['content']);
                            }
                            $dir = getcwd();
                            chdir($tmpDir);
                            exec("zip archive.zip *");

                            $model->file = file_get_contents("archive.zip");
                            $model->source_file = "archive.zip";

                            exec("rm -rf " . $tmpDir);
                            chdir($dir);
                        }
                    }
                    if (isset($_POST['input'])) {
                        $model->input = $_POST['input'];
                    }
                }

                $this->setReply(true, "Ok");
                $client = Client::model()->find(array('condition' => "`token` = '$this->clientToken'"));
                $model->client_id = ($client == null) ? null : $client->name;
                $model->request_id = $this->requestRecord->id;
                $model->save();
            } else {
                $this->setReply(false, $model->getErrors());
            }
        }
    }

}

?>
